//
//  BufferAllocatorTest.cpp
//  MNNTests
//
//  Created by MNN on 2019/01/16.
//  Copyright © 2018, Alibaba Group Holding Limited
//

#include "MNNTestSuite.h"
#include "core/BufferAllocator.hpp"
#include "core/MNNMemoryUtils.h"

using namespace MNN;
#ifndef _MSC_VER
class BufferAllocatorTest : public MNNTestCase {
public:
    virtual ~BufferAllocatorTest() = default;
    static void dynamic_allocator_test(const std::vector<int>& seqs) {
        EagerBufferAllocator allocator(BufferAllocator::Allocator::createDefault());
        std::vector<MemChunk> allocs;
        for (int i = 0; i < seqs.size(); i++) {
            int code = seqs[i];
            if (code > 0) {
                auto res = allocator.alloc(code);
                allocs.push_back(res);
            } else {
                allocator.free(allocs[abs(code) - 1]);
            }
        }
        printf("BufferAllocator total size : %lu B, %f M\n", allocator.totalSize(), allocator.totalSize() / 1024.f / 1024.f);
    }
    static void defer_allocator_test(const std::vector<int>& seqs) {
        DeferBufferAllocator allocator(BufferAllocator::Allocator::createDefault());
        std::vector<MemChunk> allocs;
        int usage_num = 0;
        for (int i = 0; i < seqs.size(); i++) {
            int code = seqs[i];
            if (code > 0) {
                auto res = allocator.alloc(code);
                allocs.push_back(res);
            } else {
                allocator.free(allocs[abs(code) - 1]);
            }
        }
        size_t totalSize = allocator.compute();
        printf("StaticAllocator total size : %lu B, %f M\n", totalSize, totalSize / 1024.f / 1024.f);
    }
    virtual bool run(int precision) {
        // case 1
        {
            /*
            seqs mean as below:
            {
                auto p1 = allocator.alloc(10);
                allocator.free(p1);
                auto p2 = allocator.alloc(2);
                auto p3 = allocator.alloc(7);
                allocator.free(p2);
                auto p4 = allocator.alloc(3);
                auto p5 = allocator.alloc(2);
                allocator.free(p3);
                auto p6 = allocator.alloc(8);
                allocator.free(p6);
                auto p7 = allocator.alloc(4);
                auto p8 = allocator.alloc(4);
                allocator.free(p7);
                auto p9 = allocator.alloc(6);
                allocator.free(p4);
                allocator.free(p5);
                allocator.free(p8);
                allocator.free(p9);
            }
            */
            std::vector<int> seqs {10, -1, 2, 7, -2, 3, 2, -3, 8, -6, 4, 4, -7, 6, -4, -5, -8, -9};
            dynamic_allocator_test(seqs); // 27 Byte
            defer_allocator_test(seqs); // 15 Byte
        }
        // case 2
        {
            std::vector<int> seqs { 75497472, 150994944, 288, -3, 288, -4, 288, -5, 288, -6, -1, 37748736, -2, 56623104, 864, -9, 864, -10, 864, -11, 864, -12, -7, 56623104, -8, 169869312, 2304, -15, 2304, -16, 2304, -17, 2304, -18, 42467328, -14, 28311552, 6912, -21, 6912, -22, 6912, -23, 6912, -24, -19, 28311552, -20, 84934656, 4608, -27, 4608, -28, 4608, -29, 4608, -30, 21233664, -26, 10616832, 13824, -33, 13824, -34, 13824, -35, 13824, -36, -31, 10616832, -32, 31850496, 6912, -39, 6912, -40, 6912, -41, 6912, -42, 7962624, -38, 3538944, 20736, -45, 20736, -46, 20736, -47, 20736, -48, -43, 3538944, -44, 10616832, 9216, -51, 9216, -52, 9216, -53, 9216, -54, 2654208, -50, 884736, 27648, -57, 27648, -58, 27648, -59, 27648, -60, -55, 884736, -56, 2654208, 9216, -63, 9216, -64, 9216, -65, 9216, -66, 663552, -62, 221184, 27648, -69, 27648, -70, 27648, -71, 27648, -72, -67, 884736, 884736, 36864, -75, -74, -68, 2654208, 9216, -77, 9216, -78, 9216, -79, 9216, -80, 2654208, 36864, -82, -76, 884736, 27648, -84, 27648, -85, 27648, -86, 27648, -87, -81, 884736, -73, -83, 884736, -88, 1769472, -89, -61, 1769472, -90, 3538944, 3538944, 73728, -94, -93, -91, 10616832, 9216, -96, 9216, -97, 9216, -98, 9216, -99, 10616832, 73728, -101, -95, 3538944, 27648, -103, 27648, -104, 27648, -105, 27648, -106, -100, 3538944, -92, -102, 3538944, -107, 7077888, -108, -49, 7077888, -109, 10616832, 10616832, 73728, -113, -112, -110, 31850496, 6912, -115, 6912, -116, 6912, -117, 6912, -118, 31850496, 147456, -120, -114, 10616832, 20736, -122, 20736, -123, 20736, -124, 20736, -125, -119, 10616832, -111, -121, 10616832, -126, 21233664, -127, -37, 21233664, -128, 28311552, 28311552, 55296, -132, -131, -129, 84934656, 4608, -134, 4608, -135, 4608, -136, 4608, -137, 84934656, 294912, -139, -133, 28311552, 13824, -141, 13824, -142, 13824, -143, 13824, -144, -138, 28311552, -130, -140, 28311552, -145, 56623104, -146, -25, 56623104, -147, 56623104, 56623104, 36864, -151, -150, -148, 169869312, 2304, -153, 2304, -154, 2304, -155, 2304, -156, 169869312, 589824, -158, -152, 56623104, 6912, -160, 6912, -161, 6912, -162, 6912, -163, -157, 56623104, -149, -159, 56623104, -164, 113246208, -165, -13, 113246208, -166, 226492416, 226492416, 18432, -170, -169, -167, 75497472, 2304, -172, 2304, -173, 2304, -174, 2304, -175, -168, 75497472, -171, -176 };
            dynamic_allocator_test(seqs); // 1134.000244 M
            defer_allocator_test(seqs); // 594.000000 M
        }
        // case 3
        {
            std::vector<int> seqs {1843200, 921600, 10368, 1728, -3, -4, -1, 921600, -2, 921600, 921600, -6, 921600, -5, -7, 921600, -8, 921600, -9, 230400, -10, 64, 32, 1536, -14, -12, 64, 768, -16, 768, -17, -13, 64, -15, 64, -18, 64, -19, 64, -20, 230400, -11, 230400, -22, -21, 230400, -23, 230400, 1536, -26, 1536, -27, 1536, -28, 1536, -29, -24, 1036800, 1536, -31, 1536, -32, 1536, -33, 1536, -34, -25, 264960, -30, 88320, 6912, -37, 6912, -38, 6912, -39, 6912, -40, -35, 323840, 2304, -42, 2304, -43, 2304, -44, 2304, -45, 323840, 18432, -47, -41, 88320, 8448, -49, 8448, -50, 8448, -51, 8448, -52, 88320, -48, -36, 353280, 2304, -55, 2304, -56, 2304, -57, 2304, -58, -53, 353280, -54, 353280, 353280, -60, 353280, -59, -61, 353280, -62, 353280, -63, 92160, -64, 92160, -65, 92160, 92160, -67, 92160, -66, -68, 92160, -69, 92160, 384, -71, 96, 9216, -74, 9216, -75, 9216, -76, -72, 384, 2304, -78, 2304, -79, 2304, -80, 2304, -81, -73, 384, -77, 384, -82, 384, -83, 384, -84, 92160, -70, -85, 92160, -86, 38400, 9216, -89, 9216, -90, 9216, -91, 9216, -92, -87, 230400, 3840, -94, 3840, -95, 3840, -96, 3840, -97, 230400, -93, 230400, 230400, -99, 230400, -98, -100, 230400, -101, 230400, 230400, -104, -102, 230400, -103, 230400, -105, 230400, 230400, -107, 230400, -106, -108, 230400, -109, 230400, 230400, -112, 960, -111, 256, 23040, -115, 23040, -116, 23040, -117, 23040, -118, -113, 960, 6144, -120, 6144, -121, 6144, -122, 6144, -123, -114, 960, -119, 960, -124, 960, -125, 960, -126, 230400, -110, -127, 230400, 230400, -130, -128, 38400, 23040, -132, 23040, -133, 23040, -134, 23040, -135, -129, 38400, -131, -88, 230400, 3840, -138, 3840, -139, 3840, -140, 3840, -141, 230400, -137, 230400, 230400, -143, 230400, -142, -144, 230400, -145, 230400, 230400, -148, -146, 230400, -147, 230400, -149, 230400, 230400, -151, 230400, -150, -152, 230400, -153, 230400, 230400, -156, 230400, 61440, 23040, -159, 23040, -160, 23040, -161, 23040, -162, -157, 235520, 235520, -163, 235520, -164, 235520, -165, 323840, -46, 235520, 8448, -169, 8448, -170, 8448, -171, 8448, -172, -167, 235520, -168, 235520, -173, 235520, -174, 235520, -166, -175, 235520, -176, 235520, 18432, -179, -177, 235520, 6144, -181, 6144, -182, 6144, -183, 6144, -184, -178, 61440, 61440, 6144, -187, 6144, -188, 6144, -189, 6144, -190, -185, 61440, -186, 61440, -191, 61440, -192, 61440, -158, 61440, 61440, -195, 960, -155, 256, 23040, -199, 23040, -200, 23040, -201, 23040, -202, -197, 960, 6144, -204, 6144, -205, 6144, -206, 6144, -207, -198, 960, -203, 960, -208, 960, -209, 960, -210, 230400, -154, -211, 230400, 230400, -214, -212, 38400, 23040, -216, 23040, -217, 23040, -218, 23040, -219, -213, 38400, -215, -136, 115200, 3840, -222, 3840, -223, 3840, -224, 3840, -225, -220, 115200, -221, 115200, 115200, -227, 115200, -226, -228, 115200, -229, 115200, -230, 28800, -231, 28800, -232, 28800, 28800, -234, 28800, -233, -235, 28800, -236, 28800, 480, -238, 128, 11520, -241, 11520, -242, 11520, -243, 11520, -244, -239, 480, 3072, -246, 3072, -247, 3072, -248, 3072, -249, -240, 480, -245, 480, -250, 480, -251, 480, -252, 28800, -237, -253, 28800, -254, 11520, 11520, -257, 11520, -258, 11520, -259, 11520, -260, -255, 34560, 4608, -262, 4608, -263, 4608, -264, 4608, -265, 34560, -261, 34560, 34560, -267, 34560, -266, -268, 34560, -269, 34560, -270, 34560, -271, 34560, -272, 34560, 34560, -274, 34560, -273, -275, 34560, -276, 34560, 576, -278, 160, 13824, -281, 13824, -282, 13824, -283, 13824, -284, -279, 576, 3840, -286, 3840, -287, 3840, -288, 3840, -289, -280, 576, -285, 576, -290, 576, -291, 576, -292, 34560, -277, -293, 34560, -294, 11520, 13824, -297, 13824, -298, 13824, -299, 13824, -300, -295, 11520, -296, -256, 69120, 4608, -303, 4608, -304, 4608, -305, 4608, -306, -301, 69120, -302, 69120, 69120, -308, 69120, -307, -309, 69120, -310, 69120, -311, 69120, -312, 69120, -313, 69120, 69120, -315, 69120, -314, -316, 69120, -317, 69120, 1152, -319, 288, 27648, -322, 27648, -323, 27648, -324, 27648, -325, -320, 1152, 6912, -327, 6912, -328, 6912, -329, 6912, -330, -321, 1152, -326, 1152, -331, 1152, -332, 1152, -333, 69120, -318, -334, 69120, -335, 23040, 27648, -338, 27648, -339, 27648, -340, 27648, -341, -336, 23040, 15360, 9216, -344, 9216, -345, 9216, -346, 9216, -347, -342, 61440, 61440, -348, 61440, -349, 61440, -350, 61440, -194, 61440, -352, 61440, -351, -353, 61440, -354, 61440, 9216, -357, -355, 61440, 6144, -359, 6144, -360, 6144, -361, 6144, -362, -356, 61440, 61440, -363, 61440, -364, 61440, -193, -196, -365, 61440, -366, 61440, 9216, -369, -367, 61440, 6144, -371, 6144, -372, 6144, -373, 6144, -374, -368, 235520, 235520, -375, 235520, -376, 235520, -377, 235520, -180, 235520, -379, 235520, -380, 235520, -378, -381, 235520, -382, 235520, 18432, -385, -383, 235520, 6144, -387, 6144, -388, 6144, -389, 6144, -390, -384, 235520, 18432, -392, 235520, 6144, -394, 6144, -395, 6144, -396, 6144, -397, -391, 235520, 18432, -399, -393, 235520, 6144, -401, 6144, -402, 6144, -403, 6144, -404, -398, 235520, 18432, -406, -400, 235520, 6144, -408, 6144, -409, 6144, -410, 6144, -411, -405, -407, 942080, 117760, 6144, -414, 6144, -415, 6144, -416, 6144, -417, -412, 44160, 44160, 14720, -418, 44160, -413, 14720, -420, 44160, 96, -424, -421, -422, 44160, -423, 44160, 14720, -426, 14720, -427, 44160, 96, -430, -425, -428, 14720, -429, 14720, -431, 14720, -432, 14720, -433, 14720, -434, 235520, 18432, -437, 235520, 6144, -439, 6144, -440, 6144, -441, 6144, -442, -436, 235520, 18432, -444, -438, 235520, 6144, -446, 6144, -447, 6144, -448, 6144, -449, -443, 88320, 6144, -451, 6144, -452, 6144, -453, 6144, -454, -445, 61440, 61440, 6144, -457, 6144, -458, 6144, -459, 6144, -460, -455, 61440, -456, 61440, -461, 61440, -462, 61440, -370, 61440, 61440, -465, 15360, -358, 15360, 6144, -469, 6144, -470, 6144, -471, 6144, -472, -467, 15360, -468, 15360, -473, 15360, -474, 15360, -343, 15360, 15360, -477, 5760, -337, 3840, 9216, -481, 9216, -482, 9216, -483, 9216, -484, -479, 15360, 15360, -485, 15360, -486, 15360, -487, 15360, -476, 15360, -489, 15360, -488, -490, 15360, -491, 15360, 4608, -494, -492, 15360, 6144, -496, 6144, -497, 6144, -498, 6144, -499, -493, 15360, 15360, -500, 15360, -501, 15360, -475, -478, -502, 15360, -503, 15360, 4608, -506, -504, 15360, 6144, -508, 6144, -509, 6144, -510, 6144, -511, -505, 61440, 61440, -512, 61440, -513, 61440, -514, 61440, -464, 61440, -516, 61440, -515, -517, 61440, -518, 61440, 9216, -521, -519, 61440, 6144, -523, 6144, -524, 6144, -525, 6144, -526, -520, 61440, 61440, -527, 61440, -528, 61440, -463, -466, -529, 61440, -530, 61440, 9216, -533, -531, 61440, 6144, -535, 6144, -536, 6144, -537, 6144, -538, -532, 61440, 9216, -540, 61440, 6144, -542, 6144, -543, 6144, -544, 6144, -545, -539, 61440, 9216, -547, -541, 61440, 6144, -549, 6144, -550, 6144, -551, 6144, -552, -546, 23040, 6144, -554, 6144, -555, 6144, -556, -548, 15360, -522, 15360, 6144, -559, 6144, -560, 6144, -561, 6144, -562, -557, 15360, -558, 15360, -563, 15360, -564, 15360, -507, 15360, 15360, -567, 3840, -495, 3840, 6144, -571, 6144, -572, 6144, -573, 6144, -574, -569, 3840, -570, 3840, -575, 3840, -576, 3840, -480, 3840, 3840, -579, 3840, -578, 3840, -581, 3840, -577, -580, -582, 3840, -583, 3840, 3072, -586, -584, 3840, 6144, -588, 6144, -589, 6144, -590, 6144, -591, -585, -587, 15360, 15360, -592, 15360, -593, 15360, -594, 15360, -566, 15360, -596, 15360, -595, -597, 15360, -598, 15360, 4608, -601, -599, 15360, 6144, -603, 6144, -604, 6144, -605, 6144, -606, -600, 15360, -602, 15360, -607, 15360, -608, 15360, -565, -568, -609, 15360, -610, 15360, 4608, -613, -611, 15360, 6144, -615, 6144, -616, 6144, -617, 6144, -618, -612, 15360, 4608, -620, 15360, 6144, -622, 6144, -623, 6144, -624, 6144, -625, -619, 15360, 4608, -627, -621, 15360, 6144, -629, 6144, -630, 6144, -631, 6144, -632, -626, 5760, 6144, -634, 6144, -635, 6144, -636, -628, 87840, 66240, 17280, 4320, -638, -639, -640, -450, -553, -633, 87840, 43920, -641, 43920, -642, 87840, 64, -645, -637, -643, 87840, -644, 87840, 43920, -647, 43920, -648, 87840, 64, -651, -646, -649, 43920, -650, 43920, -652, 48000, 12000, 12000, 12000, -655, 12000, -657, 12000, 12000, -656, -659, 235520, 18432, -662, 235520, 6144, -664, 6144, -665, 6144, -666, 6144, -667, -661, 235520, 18432, -669, -663, 235520, 6144, -671, 6144, -672, 6144, -673, 6144, -674, -668, 147200, 6144, -676, 6144, -677, 6144, -678, 6144, -679, -670, 61440, 9216, -681, -534, 61440, 6144, -683, 6144, -684, 6144, -685, 6144, -686, -680, 61440, 9216, -688, -682, 61440, 6144, -690, 6144, -691, 6144, -692, 6144, -693, -687, 38400, 6144, -695, 6144, -696, 6144, -697, 6144, -698, -689, 15360, 4608, -700, -614, 15360, 6144, -702, 6144, -703, 6144, -704, 6144, -705, -699, 15360, 4608, -707, -701, 15360, 6144, -709, 6144, -710, 6144, -711, 6144, -712, -706, 9600, 6144, -714, 6144, -715, 6144, -716, 6144, -717, -708, 175680, 132480, 34560, 8640, -719, -720, -721, -675, -694, -713, 175680, -718, 48000, -722, 48000, -723, 48000, -724, 48000, -725, 12000, 12000, -727, 12000, -660, -728, 12000, 12000, -730, 12000, -658, -731, 12000, 12000, -729, -733, 12000, 12000, -654, 12000, -735, 12000, -737, 12000, 12000, -736, -739, 12000, 12000, -741, 12000, -740, -742, 12000, -726, 12000, -744, 12000, -738, -745, 12000, 12000, -743, -747, 12000, -732, 12000, -746, 48000, -734, -748, -749, -750, 12000, 12000, -752, 12000, 12000, -754, 12000, 12000, -756, 12000, -751, 12000, -758, 43920, -653, 12000, -760, 48000, -753, -755, -757, -759, 48000, -762, 12000, -761, -764, 480, -763, 120, 120, 120, -766, 120, -768, 120, 120, -767, -770, 120, 120, 120, -772, -773, 120, -774, 120, 120, 120, -776, -777, 120, -778, 120, -775, -779, 120, -780, 120, -781, 120, -782, 120, -783, 120, -784, 120, -785, 120, -786, 120, -787, 120, -788, -789, 480, 480, -790, 120, 120, -792, 120, 120, -794, 120, 120, -796, 120, -791, 120, -798, 235520, -386, 480, -793, -795, -797, -799, -801, 376320, 376320, -802, 7680, 7680, 6144, -806, 6144, -807, 6144, -808, 6144, -809, -804, 7680, 6144, -811, 6144, -812, 6144, -813, 6144, -814, -805, 7680, 6144, -816, 6144, -817, 6144, -818, 6144, -819, -810, 960, 6144, -821, -815, 480, 480, -823, -820, 480, -822, 480, -824, 120, 120, -826, 120, -771, -827, 120, 120, -829, 120, -769, -830, 120, 120, -828, -832, 120, 120, -765, 120, -834, 120, -836, 120, 120, -835, -838, 120, 120, -840, 120, -839, -841, 120, -825, 120, -843, 120, -837, -844, 120, 120, -842, -846, 120, -831, 120, -845, 7680, -803, 7680, 6144, -852, 6144, -853, 6144, -854, 6144, -855, -850, 7680, 6144, -857, 6144, -858, 6144, -859, 6144, -860, -851, 7680, 6144, -862, 6144, -863, 6144, -864, 6144, -865, -856, 960, 6144, -867, -861, 240, 360, 120, -868, 480, -833, -847, -848, -849, 480, 120, -870, -872, -873, 480, -871, 160, -874, 40, 40, 40, -876, -877, 40, -878, 40, 40, 40, -880, -881, 40, -882, 40, -879, -883, 40, -884, 40, -885, 40, -886, 40, -887, 40, -888, 40, -889, 40, -890, 40, -891, 40, -892, -893, 160, 160, -894, 40, 40, -896, 40, 40, -898, 40, 40, -900, 40, -895, 40, -902, 160, -897, -899, -901, -903, -904, 125440, 125440, -905, 2560, 2560, 6144, -909, 6144, -910, 6144, -911, 6144, -912, -907, 2560, 6144, -914, 6144, -915, 6144, -916, 6144, -917, -908, 320, 6144, -919, -913, 80, 80, -921, -918, 80, -920, 40, 40, 40, -923, -924, 40, -925, 40, 40, 40, -927, -928, 40, -929, 40, -926, -930, 40, -931, 40, -932, 40, -933, 40, -934, 40, -935, 40, -936, 40, -937, 40, -938, 40, -939, -940, 160, 160, -941, 40, 40, -943, 40, 40, -945, 40, 40, -947, 40, -942, 40, -949, 160, -944, -946, -948, -950, -800, -951, 501760, 501760, -952, 501760, 10752, -955, -953, 250880, 6144, -957, 6144, -958, 6144, -959, 6144, -960, -954, 250880, 10752, -962, -956, 250880, 3072, -964, 3072, -965, 3072, -966, 3072, -967, -961, 62720, 3072, -969, 3072, -970, 3072, -971, 3072, -972, -963, 15680, 15680, 7840, -973, 15680, -974, -968, 7840, -975, 15680, 64, -979, -976, -977, 15680, -978, 15680, 7840, -981, 7840, -982, 15680, 64, -985, -980, -983, 7840, -984, 7840, -986, 2560, -906, 2560, 6144, -990, 6144, -991, 6144, -992, 6144, -993, -988, 2560, 6144, -995, 6144, -996, 6144, -997, 6144, -998, -989, 2560, 6144, -1000, 6144, -1001, 6144, -1002, 6144, -1003, -994, 640, 6144, -1005, 6144, -1006, -999, 120, 360, 120, 120, -1009, 40, -1010, 40, -1011, 40, -1012, 40, -1013, 120, 96, -1016, -1007, -1014, 40, 120, 40, 40, -1017, -1019, 40, 40, 40, -1021, -1022, 40, -1020, -1023, 40, 40, 40, -1025, -1026, 40, 40, 40, -1028, -1029, 40, -1027, -1030, 40, 40, 40, -1032, -1033, 40, 40, -1018, 40, -1035, -1036, 40, -1034, -1037, 120, -1024, -1031, -1038, 120, 120, -1040, 40, -1041, 40, -1042, 40, -1043, 40, -1044, 120, 96, -1047, -1039, -1045, 40, 40, 40, -1048, -1049, 40, 40, 40, -1051, -1052, 40, -1050, -1053, 40, 40, 40, -1055, -1056, 40, 40, 40, -1058, -1059, 40, -1057, -1060, 40, 40, 40, -1062, -1063, 40, 40, 40, -1065, -1066, 40, -1064, -1067, 120, -1054, -1061, -1068, 360, -1015, -1069, -1046, 480, -1008, -1070, -1004, 480, -1071, 160, -875, 160, -1073, 160, -1074, 160, -1075, 360, -866, 120, -1077, 120, 40, -1079, 120, -1078, 40, -1080, 120, 96, -1084, -1082, 120, -1083, 120, 40, -1086, 40, -1087, 120, 96, -1090, -1085, -1088, 120, -1089, 40, -1091, 40, -1092, -1081, -435, -922, -987, -1072, -1076, -1093, -419, -869};
            dynamic_allocator_test(seqs); // 2.648254 M
            defer_allocator_test(seqs); // 2.648254 M
        }
        return true;
    }
};
MNNTestSuiteRegister(BufferAllocatorTest, "core/buffer_allocator");
#endif
